package com.sunday.common.sharding.sphere.jdbc.study.base.sync.interrupt;

import java.util.Date;
import java.util.concurrent.TimeUnit;

/**
 * @Description:
 * @Author: zsy
 * @Create: 2023/4/4 15:30
 */
public class DeadLockCannotInterruptDemo {

    private static Object lock1 = new Object();
    private static Object lock2 = new Object();

    /**
     * synchronized锁不能被中断
     * 为了模拟synchronized锁不可中断，下面先让两个线程进入死锁，然后再用main线程去中断其中一个线程，看被中断的线程能否释放锁并被唤醒。
     * 【结论】如上图，main线程中断Thread-0后，Thread-0并不会释放锁并醒过来。同样的，ReentrantLock的tryLock或lockInterruptibly是可以被中断的。
     */
    public static void main(String[] args) throws Exception {
        Thread threadA = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (lock1) {
                    System.out.println(new Date() + " " + Thread.currentThread().getName() + " get lock1");
                    try {
                        Thread.sleep(10);
                        synchronized (lock2) {
                            System.out.println(new Date() + " " + Thread.currentThread().getName() + " get lock2");
                        }
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        });

        Thread threadB = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (lock2) {
                    System.out.println(new Date() + " " + Thread.currentThread().getName() + " get lock2");
                    try {
                        Thread.sleep(10);
                        synchronized (lock1) {
                            System.out.println(new Date() + " " + Thread.currentThread().getName() + " get lock1");
                        }
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        });

        threadA.start();
        threadB.start();

        TimeUnit.SECONDS.sleep(3);
        System.out.println("main thread begin to interrupt " + threadA.getName() + " and " + threadA.getName() + " will release lock1...");
        threadA.interrupt();
    }

}
